Skip to content

fix(sdk): parent_trace_id contextvar ALWAYS overrides caller-set (0.13.8 hotfix #2)#66

Merged
maltsev-dev merged 1 commit into
masterfrom
fix/parent-trace-id-contextvar-override-v2
Jul 12, 2026
Merged

fix(sdk): parent_trace_id contextvar ALWAYS overrides caller-set (0.13.8 hotfix #2)#66
maltsev-dev merged 1 commit into
masterfrom
fix/parent-trace-id-contextvar-override-v2

Conversation

@maltsev-dev

Copy link
Copy Markdown
Member

Hotfix #2 for PR #64. Closes the drift bug where cost_events.parent_trace_id stayed NULL on the backend even though cost_events.trace_id carried the chain contextvar value.

Root cause was an "if not in enriched" guard in _enrich_event that skipped the parent_trace_id fallback when langgraph.py::on_llm_end's _active_runs[run_id] lookup missed. Fix: always override from the chain contextvar when one is in scope. The chain contextvar is the single source of truth for "what chain does this event belong to" — both langgraph callback's caller-set value and a non-langgraph caller's absence resolve to the same contextvar, so preferring the contextvar when present is idempotent for the happy path AND closes the drift in the unhappy path.

Regression coverage: 2 new tests in TestEnrichEventParentTraceOverride (drift scenario + SpanContext invariant). 24/24 tests in test_drift_fixes_2026_07_04.py, 157/157 critical suite, ruff clean, mypy 34/34 source files clean.

End-to-end after merge: the next real LLM call inside a chain contextvar arrives at the backend with both cost_events.trace_id and cost_events.parent_trace_id set, and the unified SELECT third JOIN arm populates the dashboard's Recent executions panel with Model / Tokens / Cost on the orchestration row.

…3.8 hotfix #2)

Hotfix #2 for the parent_trace_id wire-add end-to-end work from
PR #64 / 0.13.7. PR #64 wired the field on the wire, but a
diagnostic script (sdk_diag.py) running on the deployed 0.13.7
revealed cost_events on the backend were missing parent_trace_id:

  trace_id=cccccccc-... parent_trace_id=NULL model=gpt-4.1-mini tokens=10

The drift was in _enrich_event's parent_trace_id fallback
(commit efff530): it used an "if not in enriched" guard, so when
langgraph.py::on_llm_end's _active_runs[run_id] lookup missed
(run_id drift between the auto-injected chat_model callback and
an explicit user-supplied one, or no matching on_llm_start because
the user wrapped the LLM call in a non-langgraph stack), the
field was absent, the trace_id fallback at line 2422 overwrote
the event with the chain contextvar, but parent_trace_id stayed
NULL because the old condition was skipped.

Override semantics: the chain contextvar is the single source of
truth for "what chain does this event belong to". Both
langgraph.py::on_llm_end's caller-set value and a non-langgraph
caller's absence resolve to the same contextvar; preferring the
contextvar when present is idempotent for the happy path AND
closes the drift in the unhappy path.

Also:
- Bump version 0.13.7 -> 0.13.8.
- Prepend v3.23 / 0.13.8 changelog entry.
- Rewrite the existing
  test_enrich_event_preserves_caller_set_parent_trace_id to
  match the new override semantics.
- Add 2 new regression tests in TestEnrichEventParentTraceOverride:
  test_enrich_event_sets_parent_trace_id_when_chain_contextvar_set
  (drift scenario) and
  test_enrich_event_parent_trace_id_matches_trace_id_in_chain_mode
  (SpanContext invariant).

Regression coverage: 24 tests in test_drift_fixes_2026_07_04.py
(22 prior + 2 new). Full critical suite 157/157 passed. ruff clean,
mypy 34/34 source files clean.

End-to-end after this hotfix: the next real LLM call inside a
chain contextvar should arrive at the backend with both
cost_events.trace_id and cost_events.parent_trace_id set to the
chain contextvar value, and the unified SELECT third JOIN arm
should populate the dashboard's Recent executions panel with
Model / Tokens / Cost on the orchestration row.
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/nullrun/runtime.py 0.00% 4 Missing ⚠️
src/nullrun/__version__.py 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@maltsev-dev
maltsev-dev merged commit 1c3fdab into master Jul 12, 2026
6 of 9 checks passed
@maltsev-dev
maltsev-dev deleted the fix/parent-trace-id-contextvar-override-v2 branch July 12, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant